package javase.module2.task04;
/*
多态的特点
1. 当父类类型的引用指向子类类型的对象时，父类类型的引用可以直接调用父类独有的方法
2. 当父类类型的引用指向子类类型的对象时，父类类型的引用不可以直接调用子类类型的独有方法
3. 对于父子类都有的非静态方法来说，编译阶段调用父类版本，运行阶段调用子类重写的版本（动态绑定）
4. 对于父子类中都有的静态方法来说，编译和运行都调用父类中的静态方法
数据类型的转换
1. 有两种：强制类型转换，自动类型转换
2. 自动类型转换主要指小类型向大类型的转换，也就是子类转父类，向上转型
3. 强制类型的转换主要指大类型向小类型的转换，也就是父类转子类，向下转或显示类型转换
4. 只能在父子类关系中进行转换
5. 若强制转换的类型不是该引用真正指向的数据类型的则编译通过，运行阶段会报异常
6. 为了避免上述错误发生，应该在强转之前进行判断，如：
    if (引用变量 instanceof 数据类型)
    判断引用变量指向的对象是否为后面的数据类型
 */
public class ShapeRectTest {
    public static void main(String[] args) {
        // 1.声明shape类型的引用指向Shape类型的对象
        Shape s1 = new Shape( 1,2 );
        s1.show();
        // 2.声明Rect类型的引用指向Rect类型的对象
        System.out.println("+++++++++++++++++++++++++++++++++++++++++");
        Rect r1 = new Rect(3,4,5,6);
        // 当Rect当中没有写show方法时，只能调用父类的show方法
        // 重写show后，Rect对象调用本身show方法
        r1.show();
        // 3.声明shape类型的引用指向Rect类型的对象
        System.out.println("+++++++++++++++++++++++++++++++++++++++++");
        // 子类向父类的转换，小到大
        Shape sr = new Rect(7,8,9,10);
        // 当Rect类中重写show方法后，父类创建子类对象时，调用的是子类show方法
        // 在编译阶段使用Shape类的方法，在运行阶段调用Rect类中的方法
        // 类似于披着羊皮的狼
        sr.show();

        // 4.测试Shape类型的引用能否直接调用父类和子类独有的方法？？？
        System.out.println("=========================================");
        int ia = sr.getX();
//        sr.getLen();   // Shape类中找不到getLen方法
        System.out.println("获取到的X坐标是："+ia);
        System.out.println("=========================================");
        // 调用静态方法
        sr.test(); // 提示：不建议使用引用.的方式访问
        Shape.test(); // 建议只用类名.的方式访问

        System.out.println("=========================================");
        // 使用父类类型的引用调用子类独有方法的方式
        // 父类类型转向子类类型，大到小的转换，需要强制转换
        int ib = ((Rect) sr).getLen();
        System.out.println("获取到的长度是："+ib);

        // 强制类型转换要求必须要有继承关系
        // String str1 = (String) sr;

        // 希望将shape类型强制转换成circle类型，下面没报错
        // Circle c1 = (Circle) sr;  //编译ok，运行报错，classcastException类型转换异常
        System.out.println("=========================================");

        // 先判断在转换类型
        // 判断sr指向堆区中的对象是否为Circle类型
        if (sr instanceof Circle) {
            System.out.println("可以放心的转换了");
            Circle c1 = (Circle)sr;
        } else {
            System.out.println("强转有风险，操作需谨慎");
        }
    }
}
